local idx = 1;
local name;

-- screen fun
local screen = SCREENMAN:GetTopScreen();
local callingScreen;
if screen then callingScreen = screen:GetName();
else callingScreen = "ScreenHSV";
end;
-- end screen fun

local Enabled = {
	Hue = true,
	Sat = true,
	Val = true,
	Alp = THEME:GetMetric(callingScreen,"AllowEditingAlpha") or THEME:GetMetric("ScreenHSV","AllowEditingAlpha"),
	Exit = true,
}

-- xxx: this code is slanted towards Player#Filter
local player;
if callingScreen == "ScreenOptionsFilterP2" then
	player = "P2"
else
	player = "P1";
end;
-- determine player's color
local prefColor = GetUserPref("FilterColor"..player);

-- write fallback
if prefColor == nil then
	SetUserPref("FilterColor"..player, "#"..ColorToHex( color("0,0,0,0.5") ) );
	prefColor = GetUserPref("FilterColor"..player);
end;

local UserColor;
if prefColor then 
	UserColor = ColorToHSV( color(prefColor) );
else
	UserColor = ColorToHSV( color("0,0,0,0.5") );
end;

local userH = UserColor.Hue;
local userS = UserColor.Sat;
local userV = UserColor.Value;
local userA = UserColor.Alpha;

local sliderLeft  = SCREEN_CENTER_X-252;
local sliderRight = SCREEN_CENTER_X+252;

local holdMovesByFull = 5;

local moveByClamped = 0.01;
local holdMovesByClamped = 0.1;

local t = Def.ActorFrame{
	Def.Actor{
		OffCommand=function(self)
			SetUserPref("FilterColor"..player, "#"..ColorToHex( HSVA(userH,userS,userV,userA) ) );
		end;
	};
	
	--[[ output values ]]
	Def.Quad{
		InitCommand=cmd(CenterX;y,SCREEN_TOP+64;zoomto,SCREEN_WIDTH*0.9,28;diffuse,color("1,1,1,0.45");fadeleft,0.15;faderight,0.15;diffusebottomedge,color("0.8,0.8,0.8,0.45"));
	};

	AutoText("frutiger")..{
		Name="HueText";
		InitCommand=cmd(x,SCREEN_CENTER_X*0.5;y,SCREEN_TOP+64;shadowlength,1;NoStroke);
	};

	AutoText("frutiger")..{
		Name="SatText";
		InitCommand=cmd(x,SCREEN_CENTER_X;y,SCREEN_TOP+64;shadowlength,1;NoStroke);
	};

	AutoText("frutiger")..{
		Name="ValText";
		InitCommand=cmd(x,SCREEN_CENTER_X*1.5;y,SCREEN_TOP+64;shadowlength,1;NoStroke);
	};

	AutoText("frutiger")..{
		Name="ColorHexText";
		InitCommand=cmd(x,SCREEN_CENTER_X*0.25;y,SCREEN_TOP+144;shadowlength,1;diffuse,color("#FFFFFF");zoom,0.8;NoStroke);
	};

	AutoText("frutiger")..{
		Name="ColorRGBANormalText";
		InitCommand=cmd(x,SCREEN_CENTER_X;y,SCREEN_TOP+144;shadowlength,1;diffuse,color("#FFFFFF");zoom,0.8;NoStroke);
	};

	AutoText("frutiger")..{
		Name="ColorRGBAText";
		InitCommand=cmd(x,SCREEN_CENTER_X*1.75;y,SCREEN_TOP+144;shadowlength,1;diffuse,color("#FFFFFF");zoom,0.8;NoStroke);
	};

	-- outline
	Def.Quad{
		InitCommand=cmd(visible,false;CenterX;y,SCREEN_TOP+104;zoomto,(SCREEN_WIDTH*0.8)+2,32+2;diffuse,color("0,0,0,1"));
	};
	-- color
	Def.Quad{
		Name="ColorPreview";
		InitCommand=cmd(CenterX;y,SCREEN_TOP+104;zoomto,(SCREEN_WIDTH*0.8),32);
	};
	--[[ /output values ]]

	--[[ part 1: hue bar (0-360) ]]
	LoadActor("_hue")..{
		InitCommand=cmd(CenterX;y,SCREEN_CENTER_Y*0.75);
		HSVFocusChangedMessageCommand=function(self,params)
			if params.NewIndex == 0 then
				idx = 1;

				self:finishtweening();
				self:accelerate(0.2);
				self:diffuse( color("1,1,1,1") );
			else
				self:finishtweening();
				self:accelerate(0.2);
				self:diffuse( color("0.5,0.5,0.5,1") );
			end;
		end;
	};

	Def.ActorFrame{
		Name="HueSlider";
		InitCommand=function(self)
			self:x( scale(userH, 0, 360, sliderLeft, sliderRight) );
			self:y(SCREEN_CENTER_Y*0.75);
		end;

		CodeMessageCommand=function(self,params)
			if not Enabled['Hue'] then return; end;

			if idx == 1 then
				if params.Name == "MoveLeft" then
					if( userH > 0 ) then
						userH = userH - 1;
					end;
				end;

				if params.Name == "MoveRight" then
					if( userH < 360 ) then
						userH = userH + 1;
					end;
				end;

				if params.Name == "HoldLeft" then
					if( (userH - holdMovesByFull) > 0 ) then
						userH = userH - holdMovesByFull;
					else userH = 0;
					end;
				end;

				if params.Name == "HoldRight" then
					if( (userH + holdMovesByFull) < 360 ) then
						userH = userH + holdMovesByFull;
					else userH = 360;
					end;
				end;

				self:x( scale(userH, 0, 360, sliderLeft, sliderRight) );
			end;
		end;

		Def.Quad{
			Name="HueSliderBG";
			InitCommand=cmd(zoomto,8,32;diffuse,color("0,0,0,1"));
		};

		Def.Quad{
			Name="HueSliderProper";
			InitCommand=cmd(zoomto,6,30;diffuse,color("0.8,0.8,0.8,1");diffusetopedge,color("1,1,1,1");diffusebottomedge,color("0.5,0.5,0.5,1"));
		};
	};
	--[[ /part 1: hue bar ]]

	--[[ part 2: sat bar (0-1) ]]
	Def.Quad{
		Name="SaturationBar";
		InitCommand=cmd(CenterX;CenterY;zoomto,SCREEN_WIDTH*0.8,32);
		HSVFocusChangedMessageCommand=function(self,params)
			if params.NewIndex == 1 then
				idx = 2;

				self:finishtweening();
				self:accelerate(0.2);
				self:diffuse( color("1,1,1,1") );
			else
				self:finishtweening();
				self:accelerate(0.2);
				self:diffuse( HSV(userH,userS,userV/2) );
			end;
		end;
	};
	
	Def.ActorFrame{
		Name="SatSlider";
		InitCommand=function(self)
			self:x( scale(userS, 0, 1, sliderLeft, sliderRight) );
			self:y(SCREEN_CENTER_Y);
		end;

		CodeMessageCommand=function(self,params)
			if not Enabled['Sat'] then return; end;

			if idx == 2 then
				if params.Name == "MoveLeft" then
					if( userS > 0 ) then
						userS = userS - moveByClamped;
					end;
				end;

				if params.Name == "MoveRight" then
					if( userS < 1 ) then
						userS = userS + moveByClamped;
					end;
				end;

				if params.Name == "HoldLeft" then
					if( (userS - holdMovesByClamped) > 0 ) then
						userS = userS - holdMovesByClamped;
					else userS = 0;
					end;
				end;

				if params.Name == "HoldRight" then
					if( (userS + holdMovesByClamped) < 1 ) then
						userS = userS + holdMovesByClamped;
					else userS = 1;
					end;
				end;

				self:x( scale(userS, 0, 1, sliderLeft, sliderRight) );
			end;
		end;

		Def.Quad{
			Name="SatSliderBG";
			InitCommand=cmd(zoomto,8,32;diffuse,color("0,0,0,1"));
		};

		Def.Quad{
			Name="SatSliderProper";
			InitCommand=cmd(zoomto,6,30;diffuse,color("0.8,0.8,0.8,1");diffusetopedge,color("1,1,1,1");diffusebottomedge,color("0.5,0.5,0.5,1"));
		};
	};
	--[[ /part 2: sat bar ]]

	--[[ part 3: val bar (0-1) ]]
	Def.Quad{
		Name="ValueBar";
		InitCommand=cmd(CenterX;y,SCREEN_CENTER_Y*1.25;zoomto,SCREEN_WIDTH*0.8,32);
		HSVFocusChangedMessageCommand=function(self,params)
			if params.NewIndex == 2 then
				idx = 3;

				self:finishtweening();
				self:accelerate(0.2);
				self:diffuse( color("0.01,0.01,0.01,1") );
			else
				self:finishtweening();
				self:accelerate(0.2);
				self:diffuse( color("0,0,0,1") );
			end;
		end;
	};

	Def.ActorFrame{
		Name="ValSlider";
		InitCommand=function(self)
			self:x( scale(userV, 0, 1, sliderLeft, sliderRight) );
			self:y(SCREEN_CENTER_Y*1.25);
		end;

		CodeMessageCommand=function(self,params)
			if not Enabled['Val'] then return; end;

			if idx == 3 then
				if params.Name == "MoveLeft" then
					if( userV > 0 ) then
						userV = userV - moveByClamped;
					end;
				end;

				if params.Name == "MoveRight" then
					if( userV < 1 ) then
						userV = userV + moveByClamped;
					end;
				end;

				if params.Name == "HoldLeft" then
					if( (userV - holdMovesByClamped) > 0 ) then
						userV = userV - holdMovesByClamped;
					else userV = 0;
					end;
				end;

				if params.Name == "HoldRight" then
					if( (userV + holdMovesByClamped) < 1 ) then
						userV = userV + holdMovesByClamped;
					else userV = 1;
					end;
				end;

				self:x( scale(userV, 0, 1, sliderLeft, sliderRight) );
			end;
		end;

		Def.Quad{
			Name="ValSliderBG";
			InitCommand=cmd(zoomto,8,32;diffuse,color("0,0,0,1"));
		};

		Def.Quad{
			Name="ValSliderProper";
			InitCommand=cmd(zoomto,6,30;diffuse,color("0.8,0.8,0.8,1");diffusetopedge,color("1,1,1,1");diffusebottomedge,color("0.5,0.5,0.5,1"));
		};
	};
	--[[ /part 3: val bar ]]

	--[[ part 4: alpha bar (0-1) ]]
	Def.Quad{
		Name="AlphaBar";
		InitCommand=cmd(CenterX;y,SCREEN_CENTER_Y*1.5;zoomto,SCREEN_WIDTH*0.8,32;fadeleft,1);

		HSVFocusChangedMessageCommand=function(self,params)
			if params.NewIndex == 3 then
				idx = 4;

				self:finishtweening();
				self:accelerate(0.2);
				self:diffuse( HSV(userH, userS, userV) );
			else
				self:finishtweening();
				self:accelerate(0.2);
				self:diffuse( HSV(userH, userS, userV/2) );
			end;
		end;
	};

	Def.ActorFrame{
		Name="AlphaSlider";
		InitCommand=function(self)
			self:x( scale(userA, 0, 1, sliderLeft, sliderRight) );
			self:y(SCREEN_CENTER_Y*1.5);
		end;

		CodeMessageCommand=function(self,params)
			if idx == 4 then
				if params.Name == "MoveLeft" then
					if( userA > 0 ) then
						userA = userA - moveByClamped;
					end;
				end;

				if params.Name == "MoveRight" then
					if( userA < 1 ) then
						userA = userA + moveByClamped;
					end;
				end;

				if params.Name == "HoldLeft" then
					if( (userA - holdMovesByClamped) > 0 ) then
						userA = userA - holdMovesByClamped;
					else userA = 0;
					end;
				end;

				if params.Name == "HoldRight" then
					if( (userA + holdMovesByClamped) < 1 ) then
						userA = userA + holdMovesByClamped;
					else userA = 1;
					end;
				end;

				self:x( scale(userA, 0, 1, sliderLeft, sliderRight) );
			end;
		end;

		Def.Quad{
			Name="AlphaSliderBG";
			InitCommand=cmd(zoomto,8,32;diffuse,color("0,0,0,1"));
		};

		Def.Quad{
			Name="AlphaSliderProper";
			InitCommand=cmd(zoomto,6,30;diffuse,color("0.8,0.8,0.8,1");diffusetopedge,color("1,1,1,1");diffusebottomedge,color("0.5,0.5,0.5,1"));
		};
	};
	--[[ /part 4: alpha bar ]]
};

local function round(val, places)
	if (places) then
		return math.floor( (val * 10^places) + 0.5) / (10^places);
	else
		return math.floor(val+0.5);
	end;
end;

function UpdateHSV(self)
	local CurrentColor = {
		Hue = userH,
		Sat = userS,
		Value = userV,
		Alpha = userA
	};

	userH = round(userH, 2);
	userS = round(userS, 2);
	userV = round(userV, 2);

	local c = self:GetChildren();
	c.HueText:settext("Hue: " .. userH);
	c.SatText:settext("Sat: " .. userS);
	c.ValText:settext("Val: " .. userV);

	c.HueText:diffuse( HSVA(userH,1,1,1) );
	c.SatText:diffuse( HSVA(userH,userS,1,1) );
	c.ValText:diffuse( HSVA(userH,1,userV,1) );

	--c.ColorPreview:diffuse( HSV(userH,userS,userV) );
	c.ColorPreview:diffuse( HSVA(userH,userS,userV,userA) );

	-- focus diffusing
	if idx ~= 2 then -- Saturation
		c.SaturationBar:diffuse( HSVA(userH,0,userV/2,1) );
		c.SaturationBar:diffuserightedge( HSVA(userH,1,userV/2,1) );
	else
		c.SaturationBar:diffuse( HSVA(userH,0,userV,1) );
		c.SaturationBar:diffuserightedge( HSVA(userH,1,userV,1) );
	end;

	if idx ~= 3 then -- Value
		c.ValueBar:diffuserightedge( HSVA(userH,userS,0.5,1) );
	else
		c.ValueBar:diffuserightedge( HSVA(userH,userS,1,1) );
	end;

	if idx ~= 4 then -- alpha
		c.AlphaBar:diffuse( HSVA(userH,userS,userV/2,1) );
		c.AlphaBar:diffuserightedge( HSVA(userH,userS,userV/2,1) );
	else
		c.AlphaBar:diffuse( HSVA(userH,userS,userV,1) );
		c.AlphaBar:diffuserightedge( HSVA(userH,userS,userV,1) );
	end;

	-- colortext
	local color = HSVToColor( CurrentColor );
	local colorX = ColorToHex(color);

	--[[ default (0-1) ]]
	local r = color[1];
	local g = color[2];
	local b = color[3];
	local a = color[4];

	r = round(r, 2);
	g = round(g, 2);
	b = round(b, 2);

	local rgba = "("..r..","..g..","..b..","..a..")";
	c.ColorRGBAText:settext(rgba);

	--[[ normalized (0-255) ]]
	local rN = scale(color[1], 0, 1, 0, 255);
	local gN = scale(color[2], 0, 1, 0, 255);
	local bN = scale(color[3], 0, 1, 0, 255);
	local aN = scale(color[4], 0, 1, 0, 255);

	-- normalize down to ints
	rN = math.ceil(rN);
	gN = math.ceil(gN);
	bN = math.ceil(bN);
	aN = math.ceil(aN);

	local rgbaN = "("..rN..","..gN..","..bN..","..aN..")";
	c.ColorRGBANormalText:settext(rgbaN);

	--[[ hex ]]
	local rX = colorX[1];
	local gX = colorX[2];
	local bX = colorX[3];
	local aX = colorX[4];

	c.ColorHexText:settext("#"..colorX);
end;

t.InitCommand=cmd(SetUpdateFunction,UpdateHSV);

return t;